package com.wanjia.bpsapi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wanjia.bpsapi.constant.CalType;
import com.wanjia.bpsapi.exception.DatabaseException;
import com.wanjia.bpsapi.mapper.ParamMapper;
import com.wanjia.bpsapi.mapper.VegeParamMapper;
import com.wanjia.bpsapi.mapper.VegetableMapper;
import com.wanjia.bpsapi.pojo.dto.VegeParamTable;
import com.wanjia.bpsapi.pojo.dto.VegeParamUpdate;
import com.wanjia.bpsapi.pojo.entity.VegeParam;
import com.wanjia.bpsapi.service.IVegeParamService;
import com.wanjia.bpsapi.util.PageUtil;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 成本换算关系表 服务实现类
 * </p>
 *
 * @author wyn
 * @since 2023-02-13
 */
@Service
public class VegeParamServiceImpl extends ServiceImpl<VegeParamMapper, VegeParam> implements IVegeParamService {

    private static final String SEPARATOR = ",";

    @Setter(onMethod_ = @Autowired)
    private VegeParamMapper mapper;

    @Setter(onMethod_ = @Autowired)
    private VegetableMapper vegetableMapper;

    @Setter(onMethod_ = @Autowired)
    private ParamMapper paramMapper;

    @Override
    public Page<VegeParamTable> pageVegeParam(Long vegeId, Long paramId, Integer pageNo, Integer pageSize) {
        // 查询分页数据与总数
        List<VegeParamTable> records = mapper.pageConversion(vegeId, paramId, pageNo, pageSize);
        Long total = mapper.countConversion(vegeId, paramId);

        // 构建分页数据并返回
        return PageUtil.page(pageNo, pageSize, total, records);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVegeParam(List<VegeParamUpdate> updates) {
        if (CollUtil.isNotEmpty(updates)) {
            updates.forEach(u -> {
                if (mapper.update(u) != 1) {
                    throw new DatabaseException(StrUtil.format("换算表数据[{}]更新失败", u));
                }
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void fixData() {
        // 菜品/成本项数据整合
        List<Long> vegetableIdList = vegetableMapper.selectIdList();
        List<Long> paramIdList = paramMapper.selectIdList();

        // 冗余数据清理
        QueryWrapper<VegeParam> wrapper = new QueryWrapper<>();
        boolean allNotEmpty = !vegetableIdList.isEmpty() && !paramIdList.isEmpty();
        if (allNotEmpty) {
            wrapper.notIn("vege_id", vegetableIdList)
                    .or().isNull("vege_id")
                    .or().notIn("param_id", paramIdList)
                    .or().isNull("param_id");
        }
        mapper.delete(wrapper);

        // 缺失数据补充生成
        if (allNotEmpty) {
            List<VegeParam> update = new ArrayList<>();
            List<VegeParam> list = mapper.selectList(new QueryWrapper<>());
            List<Long> stableParamIdList = Optional.ofNullable(paramMapper.selectIdListByCaltype(CalType.DISTANCE.code()))
                    .orElseGet(ArrayList::new);
            Set<String> keySet = Optional.ofNullable(list)
                    .orElseGet(ArrayList::new)
                    .stream()
                    .map(vp -> vp.getVegeId() + SEPARATOR + vp.getParamId())
                    .collect(Collectors.toSet());
            for (Long vegeId : vegetableIdList) {
                for (Long paramId : paramIdList) {
                    String key = vegeId + SEPARATOR + paramId;
                    if (!keySet.contains(key)) {
                        VegeParam vp = new VegeParam();
                        vp.setParamId(paramId);
                        vp.setVegeId(vegeId);
                        if (stableParamIdList.contains(paramId)) {
                            vp.setConversion(BigDecimal.ONE);
                        }
                        update.add(vp);
                    }
                }
            }
            if (!update.isEmpty()) {
                saveBatch(update);
            }
        }
    }
}
